/***************************************************
> Copyright (C) 2024 ==LX== All rights reserved.
> File Name: UserServer.c
> Author: lx
> Mail:2998218073@qq.com 
> Created Time: 2024年12月04日 星期三 14时10分33秒
***************************************************/

#include "UserServer.h"
#include "logfile.h"

int isrun = 1;
int server_socket = 0;
MYSQL* mysql = NULL;
extern int epfd;
pthread_mutex_t mysql_mutex;

void handle_signal(int signum)
{
	if (signum == SIGINT)
	{
		isrun = 0;
		close(server_socket);
		exit(0);
	}
}

void parseJson(const char* p, void* arg)
{
	Use s;
	cJSON* root = cJSON_Parse(p);
	if (root == NULL)
	{
		logMessage(LOG_ERROR, "fail:%s line:%d file:%s", cJSON_GetErrorPtr(), __LINE__, __FUNCTION__);
		printf("JSON解析失败，请检查输入的JSON数据格式是否正确\n");
		return;
	}

	cJSON* order = cJSON_GetObjectItem(root, "order");
	cJSON* name = cJSON_GetObjectItem(root, "name");
	cJSON* passwd = cJSON_GetObjectItem(root, "pwd");
	cJSON* new_pwd = cJSON_GetObjectItem(root, "new_pwd");

	strncpy(s.order, cJSON_GetStringValue(order), sizeof(s.order) - 1);
	s.order[sizeof(s.order) - 1] = '\0';  // 确保字符串以'\0'结尾
	strncpy(s.name, cJSON_GetStringValue(name), sizeof(s.name) - 1);
	s.name[sizeof(s.name) - 1] = '\0';
	strncpy(s.pwd, cJSON_GetStringValue(passwd), sizeof(s.pwd) - 1);
	s.pwd[sizeof(s.pwd) - 1] = '\0';
	strncpy(s.new_pwd, cJSON_GetStringValue(new_pwd), sizeof(s.new_pwd) - 1);
	s.new_pwd[sizeof(s.new_pwd) - 1] = '\0';

	printf("or:%s,na:%s,pwd:%s,new_pwd:%s\n", s.order, s.name, s.pwd, s.new_pwd);
	if (strcmp(s.order, "login") == 0)
	{
		int temp = query_data(s);
		if (temp == 1)
		{
			send_response(((ClientType*)arg)->fd, "用户登录成功");
		}
		else if (temp == 2)
		{
			send_response(((ClientType*)arg)->fd, "管理员登录成功");
		}
		else
		{
			send_response(((ClientType*)arg)->fd, "账户或密码错误，登录失败");
		}
	}
	if (strcmp(s.order, "register") == 0)
	{
		//先检查用户名是否已存在
		int exists = check_username_exists(s.name);
		if (exists == 1)
		{
			send_response(((ClientType*)arg)->fd, "用户名已存在，注册失败");
			return;
		}

		int flag = insert_data(s);
		if (flag == -1)
		{
			send_response(((ClientType*)arg)->fd, "注册失败");
			printf("入库失败\n");
		}
		else if (flag == 0)
		{
			send_response(((ClientType*)arg)->fd, "注册成功");
			printf("入库成功\n");
		}
	}
	if (strcmp(s.order, "modify") == 0)
	{
		int val = check_username_exists(s.name);
		if (val == 1)
		{
			int result = update_password(s);
			if (result == 0)
			{
				printf("密码修改成功\n");
				send_response(((ClientType*)arg)->fd, "密码修改成功");
			}
			else
			{
				printf("密码修改失败\n");
				send_response(((ClientType*)arg)->fd, "密码修改失败");
			}
		}
		else
		{
			printf("用户名错误，密码修改失败\n");
			send_response(((ClientType*)arg)->fd, "用户名错误，密码修改失败");
		}
	}
	if (strcmp(s.order, "delete") == 0)  // 注销用户
	{
		int res = delete_user(s);
		if (res == 0)
		{
			printf("用户注销成功\n");
			send_response(((ClientType*)arg)->fd, "用户注销成功");
		}
		else
		{
			printf("用户注销失败\n");
			send_response(((ClientType*)arg)->fd, "用户注销失败");
		}
	}
	cJSON_Delete(root);
}

void* read_msg(void* arg)
{
	ClientType ct = *(ClientType*)arg;
	char buf[1024] = { 0 };
	struct epoll_event ev;
	ev.events = EPOLLIN | EPOLLET;
	ev.data.fd = ct.fd;
	while (1)
	{
		memset(buf, 0, sizeof(buf));
		int size = read(ct.fd, buf, 1023);

		if (size == -1)
		{
			if (errno == EAGAIN || errno == EWOULDBLOCK)
			{
				continue;  // 暂时无数据可读，继续等待下次读取
			}
			else
			{
				// 其他错误，关闭连接，移除epoll事件等操作
				epoll_ctl(ct.epfd, EPOLL_CTL_DEL, ct.fd, &ev);
				close(ct.fd);
				return 0;
			}
		}
		//断开连接
		if (size == 0)
		{
			epoll_ctl(ct.epfd, EPOLL_CTL_DEL, ct.fd, &ev);
			printf("%d 客户端已断开连接\n",ct.fd);
			close(ct.fd);
		}
		if (size > 0)
		{
			//解包
			parseJson(buf, &ct);
		}
	}
}

int insert_data(Use use)
{
	pthread_mutex_lock(&mysql_mutex);
	char buf[1024] = { 0 };
	sprintf(buf, "insert into accountinfo (username,passwd) values ('%s','%s')", use.name, use.pwd);
	int ret = mysql_real_query(mysql, buf, strlen(buf));
	if (ret != 0)
	{
		logMessage(LOG_ERROR, "fail reaons:%s line:%d file:%s", mysql_error(mysql), __LINE__, __FUNCTION__);
		printf("数据入库失败:%s\n", mysql_error(mysql));
		pthread_mutex_unlock(&mysql_mutex);
		return -1;
	}
	pthread_mutex_unlock(&mysql_mutex);
	return 0;
}
int query_data(Use use)
{
	pthread_mutex_lock(&mysql_mutex);
	MYSQL_RES* res = NULL;
	MYSQL_ROW row;
	//MYSQL_FIELD* field = NULL;
	int i = 0;
	char buf[1024] = { 0 };
	sprintf(buf, "select username,passwd,perm from accountinfo");
	int ret = mysql_real_query(mysql, buf, strlen(buf));
	if (ret != 0)
	{
		logMessage(LOG_ERROR, "fail reaons:%s line:%d file:%s", strerror(errno), __LINE__, __FUNCTION__);
		printf("%s\n", mysql_error(mysql));
		pthread_mutex_unlock(&mysql_mutex);
		return -1;
	}

	//显示查询结果
	//获得结果集
	res = mysql_store_result(mysql);
	//结果集的字段信息
	//field = mysql_fetch_fields(res);
	//遍历行/记录 
	my_ulonglong Row = mysql_num_rows(res);
	if (Row < 1)
	{
		pthread_mutex_unlock(&mysql_mutex);
		return -1;
	}
	//遍历列/字段个数
	//int col = mysql_num_fields(res);
	for (i = 0; i < Row; i++)
	{
		row = mysql_fetch_row(res);
		//比较row[0]  --name   row[1] -- passwd 
		if (strcmp(use.name, row[0]) == 0 && strcmp(use.pwd, row[1]) == 0)
		{
			if (strcmp("1", row[2]) == 0)
			{
				pthread_mutex_unlock(&mysql_mutex);
				return 2;

			}
			pthread_mutex_unlock(&mysql_mutex);
			return 1;
		}
	}
	if (res != NULL)
	{
		mysql_free_result(res);
	}
	pthread_mutex_unlock(&mysql_mutex);
	return 0;
}
// 发送消息给客户端
void send_response(int client_fd, const char* message)
{
	pthread_mutex_lock(&mysql_mutex);
	int len = strlen(message);
	int sent_bytes = 0;
	while (sent_bytes < len)
	{
		int ret = write(client_fd, message + sent_bytes, len - sent_bytes);
		if (ret == -1)
		{
			if (errno == EAGAIN || errno == EWOULDBLOCK)
			{
				// 遇到缓冲区满等情况，稍作等待后再尝试发送
				usleep(1000);
				continue;
			}
			else
			{
				printf("123123\n");
				// 发送出现其他严重错误，关闭连接
				close(client_fd);
				pthread_mutex_unlock(&mysql_mutex);
				return;
			}
		}
		sent_bytes += ret;
	}
	pthread_mutex_unlock(&mysql_mutex);
}
int check_username_exists(const char* username)
{
	pthread_mutex_lock(&mysql_mutex);
	MYSQL_RES* res = NULL;
	//MYSQL_ROW row;
	char buf[1024] = { 0 };
	sprintf(buf, "select username,passwd from accountinfo where username = '%s'", username);
	int ret = mysql_real_query(mysql, buf, strlen(buf));
	if (ret != 0)
	{
		logMessage(LOG_ERROR, "fail reaons:%s line:%d file:%s", mysql_error(mysql), __LINE__, __FUNCTION__);
		pthread_mutex_unlock(&mysql_mutex);
		return -1;
	}

	res = mysql_store_result(mysql);
	
	if (res == NULL)
	{
		pthread_mutex_unlock(&mysql_mutex);
		return 0;
	}

	if (mysql_num_rows(res) > 0)
	{
		pthread_mutex_unlock(&mysql_mutex);
		return 1;
	}
	pthread_mutex_unlock(&mysql_mutex);
	return 0;
}

// 修改密码
int update_password(Use use)
{
	pthread_mutex_lock(&mysql_mutex);
	char buf[1024] = { 0 };
	sprintf(buf, "update accountinfo set passwd = '%s' where username = '%s'", use.new_pwd, use.name);
	int ret = mysql_real_query(mysql, buf, strlen(buf));
	if (ret != 0)
	{
		logMessage(LOG_ERROR, "fail reaons:%s line:%d file:%s", mysql_error(mysql), __LINE__, __FUNCTION__);
		printf("密码更新失败:%s\n", mysql_error(mysql));
		pthread_mutex_unlock(&mysql_mutex);
		return -1;
	}
	pthread_mutex_unlock(&mysql_mutex);
	return 0;
} 
// 用户注销
int delete_user(Use use)
{
	pthread_mutex_lock(&mysql_mutex);
	char buf[1024] = { 0 };
	sprintf(buf, "delete from accountinfo where username = '%s'",use.name);
	int ret = mysql_real_query(mysql, buf, strlen(buf));
	if (ret != 0)
	{
		logMessage(LOG_ERROR, "fail reaons:%s line:%d file:%s", mysql_error(mysql), __LINE__, __FUNCTION__);
		printf("用户注销失败:%s\n", mysql_error(mysql));
		pthread_mutex_unlock(&mysql_mutex);
		return -1;
	}
	pthread_mutex_unlock(&mysql_mutex);
	return 0;
}

int db_init()
{
	//初始化mysql句柄
	mysql = mysql_init(NULL);
	if (mysql == NULL)
	{
		logMessage(LOG_ERROR, "fail reaons :%s line:%d file:%s", mysql_error(mysql), __LINE__, __FUNCTION__);
		perror("mysql_init");
		return -1;
	}

	// 初始化互斥锁
	pthread_mutex_init(&mysql_mutex, NULL);

	//连接数据库
	MYSQL* conn = mysql_real_connect(mysql, "localhost", "root", "123456", "db_lanxiao", 0, NULL, 0);
	if (conn == NULL)
	{
		logMessage(LOG_ERROR, "fail reaons:%s line:%d file:%s", strerror(errno), __LINE__, __FUNCTION__);
		perror("mysql_real_connect");
		return -1;
	}
	return 0;
}
// 线程池初始化函数
ThreadPool* thread_pool_init(int thread_num, int queue_size) 
{
	ThreadPool* pool = (ThreadPool*)malloc(sizeof(ThreadPool));
	if (pool == NULL) 
	{
		logMessage(LOG_ERROR, "fail reaons:%s line:%d file:%s", strerror(errno), __LINE__, __FUNCTION__);
		perror("malloc failed");
		return NULL;
	}

	pool->thread_count = thread_num;
	pool->queue_size = queue_size;
	pool->head = pool->tail = pool->task_count = 0;

	// 初始化线程数组
	pool->threads = (pthread_t*)malloc(pool->thread_count * sizeof(pthread_t));
	if (pool->threads == NULL) 
	{
		logMessage(LOG_ERROR, "fail reaons:%s line:%d file:%s", strerror(errno), __LINE__, __FUNCTION__);
		perror("malloc threads failed");
		free(pool);
		return NULL;
	}

	// 初始化任务队列
	pool->task_queue = (Task*)malloc(pool->queue_size * sizeof(Task));
	if (pool->task_queue == NULL) 
	{
		logMessage(LOG_ERROR, "fail reaons:%s line:%d file:%s", strerror(errno), __LINE__, __FUNCTION__);
		perror("malloc task queue failed");
		free(pool->threads);
		free(pool);
		return NULL;
	}

	// 初始化互斥锁和条件变量
	pthread_mutex_init(&pool->mutex, NULL);
	pthread_cond_init(&pool->cond, NULL);

	// 创建线程
	for (int i = 0; i < pool->thread_count; i++) 
	{
		if (pthread_create(&pool->threads[i], NULL, thread_routine, (void*)pool) != 0) 
		{
			logMessage(LOG_ERROR, "fail reaons:%s line:%d file:%s", strerror(errno), __LINE__, __FUNCTION__);
			perror("pthread_create failed");
			// 如果创建线程失败，需要清理已创建的资源
			for (int j = 0; j < i; j++) {
				pthread_cancel(pool->threads[j]);
			}
			free(pool->task_queue);
			free(pool->threads);
			free(pool);
			return NULL;
		}
	}

	return pool;
}

// 线程执行的函数，从任务队列获取任务并执行
void* thread_routine(void* arg) 
{
	ThreadPool* pool = (ThreadPool*)arg;
	while (1) {
		pthread_mutex_lock(&pool->mutex);
		// 如果任务队列为空，阻塞等待条件变量通知
		while (pool->task_count == 0) {
			pthread_cond_wait(&pool->cond, &pool->mutex);
		}

		// 取出任务
		Task task = pool->task_queue[pool->head];
		pool->head = (pool->head + 1) % pool->queue_size;
		pool->task_count--;
		pthread_mutex_unlock(&pool->mutex);

		// 执行任务，调用read_msg的函数
		ClientType ct;
		ct.epfd = epfd; 
		ct.fd = task.client_socket;
		read_msg((void*)&ct);
	}
	return NULL;
}

// 向线程池添加任务
int thread_pool_add_task(ThreadPool* pool, int client_socket, void* arg) 
{
	pthread_mutex_lock(&pool->mutex);
	if (pool->task_count == pool->queue_size)
	{
		pthread_mutex_unlock(&pool->mutex);
		return -1;  // 任务队列已满，添加失败
	}

	// 将任务添加到任务队列
	pool->task_queue[pool->tail].client_socket = client_socket;
	pool->task_queue[pool->tail].arg = arg;
	pool->tail = (pool->tail + 1) % pool->queue_size;
	pool->task_count++;

	// 通知线程有新任务
	pthread_cond_signal(&pool->cond);
	pthread_mutex_unlock(&pool->mutex);
	return 0;
}

// 线程池销毁函数，释放资源
void thread_pool_destroy(ThreadPool* pool) 
{
	pthread_mutex_destroy(&pool->mutex);
	pthread_cond_destroy(&pool->cond);
	free(pool->task_queue);
	free(pool->threads);
	free(pool);
}
